import 'dart:convert';

import 'package:im_app/im/util/MapUtil.dart';
import 'package:logger/logger.dart';
import 'package:sqflite/sqflite.dart';

import '../pojo/ImPojo.dart';
import '../util/DateUtil.dart';
import '../util/ImSingleton.dart';
import 'BaseDao.dart';

class ImModuleItemDao extends BaseDao {

  final _logger = Logger(printer: PrettyPrinter(),);

  Future<ImModuleItem?> getByModuleIdAndName(int moduleId, String name) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    List? list = await database?.rawQuery("select * from im_module_item where moduleId = ? and name = ? limit 1",
        [moduleId, name]);
    if (list != null && list.length > 0) {
      return Future.value(_toImModuleItem(list[0]));
    }
    return Future.value(null);
  }

  Future<List<ImModuleItem>> getByModuleId(int moduleId) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;

    List? list = await database?.rawQuery("select * from im_module_item where moduleId = ? order by no, updateTime",
        [moduleId]);
    return list != null ? Future.value(list.map((map)=>_toImModuleItem(map)).toList()) : Future.value([]);
  }

  Future<List<ImModuleItem>> getByNames(List<String> names) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;

    String param = names.map((p)=> '?').join(",");
    List<dynamic> params = [];
    params.addAll(names);

    List? list = await database?.rawQuery("select * from im_module_item where name in (${param})", params);
    return list != null ? Future.value(list.map((map)=>_toImModuleItem(map)).toList()) : Future.value([]);
  }

  Future<List<ImModuleItem>> getAll() async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String sql = "select * from im_module_item where status = 1";
    List<Map<String, dynamic?>>? list = await database?.rawQuery(sql);
    return list != null ? Future.value(list.map((map)=>_toImModuleItem(map)).toList()) : Future.value([]);
  }

  Future<void> batchInserts(List<ImModuleItem> imModules) async {
    if (imModules.length < 1) return;
    Database? database = ImSingleton.getInstance().dataBase;
    for (var imModule in imModules) {
      var data = _toInsertValueMap(imModule);
      int? id = await database?.insert("im_module_item", data);
      imModule.id = id;
    }
  }

  Future<void> batchUpdates(List<ImModuleItem> imModules) async {
    if (imModules.length < 1) return;
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var imModule in imModules) {
      var data = _toInsertValueMap(imModule);
      batch?.update("im_module_item", data, where: "name = ?", whereArgs:[imModule.name]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch json: " + jsonEncode(list));
  }

  Map<String, dynamic?> _toInsertValueMap(ImModuleItem imModuleItem) {
    Map<String, dynamic?> map = {};
    map['name'] = imModuleItem.name;
    map['moduleId'] = imModuleItem.moduleId;
    map['description'] = imModuleItem.description;
    map['icon'] = imModuleItem.icon;
    map['url'] = imModuleItem.url;
    map['params'] = imModuleItem.params;
    map['no'] = imModuleItem.no;
    map["type"]= imModuleItem.type?.value;
    map["status"]= imModuleItem.status?.value;
    map['createTime'] = DateUtil.formatDate(imModuleItem.createTime);
    map['updateTime'] = DateUtil.formatDate(imModuleItem.updateTime);
    return map;
  }

  ImModuleItem _toImModuleItem(Map<String, dynamic> map) {
    var moduleItem = ImModuleItem(name: MapUtil.getString(map, "name"),
        no: MapUtil.getInt(map, "no"),
        status: ImModuleItemStatus.ofValue(MapUtil.getInt(map, "status")),
        icon: MapUtil.getString(map, "icon"),
        type: ImModuleItemType.ofValue(MapUtil.getInt(map, "type"))
    );
    moduleItem.id = MapUtil.getInt(map, "id");
    moduleItem.moduleId = MapUtil.getInt(map, "moduleId");
    moduleItem.description = MapUtil.getStringOrNull(map, "description");
    moduleItem.url = MapUtil.getStringOrNull(map, "url");
    moduleItem.params = MapUtil.getStringOrNull(map, "param");
    moduleItem.createTime = MapUtil.getDate(map, "createTime");
    moduleItem.updateTime = MapUtil.getDate(map, "updateTime");
    return moduleItem;
  }
}